<!doctype html>
<html lang="zh">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no">
    <link rel="icon" href="static/img/favicon-32x32.png" sizes="32x32" type="image/png">
    <link rel="icon" href="static/img/favicon-16x16.png" sizes="16x16" type="image/png">
    <title>QuickSearch-一个纯净的、集多种搜索引擎的快捷搜索工具</title>
    <link rel="stylesheet" href="static/lib/bootstrap/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="static/lib/bootstrap-icons/font/bootstrap-icons.min.css">
    <style>
        #search-input {
            box-shadow: none;
            border: var(--bs-border-width) solid var(--bs-border-color);
            border-radius: 0;
            padding-right: 32px;
        }


        .search-container {
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .suggestions-wrap {
            position: absolute;
            overflow: auto;
            width: 100%;
            max-height: 300px;
        }

        .dropdown-item.active, .dropdown-item:active {
            color: #595c5f;
            text-decoration: none;
            background-color: rgba(0, 170, 238, .24);
        }

        @keyframes spin {
            0% {
                transform: rotate(0deg);
            }
            100% {
                transform: rotate(360deg);
            }
        }

        .spinner {
            display: inline-block;
            width: 16px;
            height: 16px;
            border: 2px solid rgba(0, 0, 0, 0.2);
            border-top-color: #007bff;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        .sp-box {
            display: flex;
            align-items: center;
            justify-content: center;
            position: absolute;
            top: 50%;
            right: 6px;
            transform: translateY(-50%);
        }

    </style>
</head>
<body>


<div class="search-container">
    <div style="width: 400px;max-width: 100%;margin-top: 12vh;" class="p-2">

        <div class="d-flex align-items-center justify-content-center flex-column  mb-3">
            <img class="mb-2 rounded-circle border border-primary-subtle" style="width: 64px;height: 64px"
                 src="./static/img/quick-128x128.png" alt="">
            <span class="text-body-secondary">QuickSearch-让您的搜索只剩下搜索</span>
        </div>

        <div class="input-group flex-nowrap">

            <button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown"
                    aria-expanded="false" id="logo-wrap"><img src="static/img/baidu.png" style="width: 16px;" alt="">
            </button>

            <ul class="dropdown-menu search-logo-dropdown-menu" style="min-width: 60px">
                <li>
                    <button class="dropdown-item active" type="button" title="百度搜索" data-index="0">
                        <img src="static/img/baidu.png" alt="百度搜索" style="width: 16px;">
                    </button>
                </li>
                <li>
                    <button class="dropdown-item" type="button" title="谷歌搜索" data-index="1">
                        <img src="static/img/google.png" style="width: 16px;"
                             alt="">
                    </button>
                </li>
                <li>
                    <button class="dropdown-item" type="button" title="必应搜索" data-index="2">
                        <img src="static/img/bing.png" style="width: 16px;"
                             alt="">
                    </button>
                </li>
                <li>
                    <button class="dropdown-item" type="button" title="360搜索" data-index="3">
                        <img src="static/img/360so.png" style="width: 16px;"
                             alt="">
                    </button>
                </li>
                <li>
                    <button class="dropdown-item" type="button" title="搜狗搜索" data-index="4">
                        <img src="static/img/sougou.png" style="width: 16px;"
                             alt="">
                    </button>
                </li>
                <li>
                    <button class="dropdown-item" type="button" title="神马搜索" data-index="5">
                        <img src="static/img/shenma.png" style="width: 16px;"
                             alt="">
                    </button>
                </li>
            </ul>

            <div class="position-relative search-input-wrap">
                <input type="text" id="search-input" class="form-control text-truncate" placeholder="请输入搜索关键词"
                       aria-label="搜索">
                <div class="sp-box">
                    <!--                    <span class="spinner"></span>-->
                </div>

            </div>


            <button class="btn btn-outline-secondary" type="button" id="fullscreen-btn">
                <i class="bi bi-fullscreen"></i>
            </button>
            <button class="btn btn-outline-secondary" type="button" id="clear-btn"><i class="bi bi-x"></i></button>
            <button class="btn btn-outline-secondary" type="button" id="search-btn"><i
                    class="bi bi-search-heart"></i></button>
        </div>
        <div class="position-relative">
            <div class="suggestions-wrap"></div>
        </div>
    </div>
</div>

<!-- Modal -->
<div class="modal fade" id="bigSearchModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg modal-fullscreen-lg-down">
        <div class="modal-content">
            <div class="modal-header">
                <h1 class="modal-title fs-5" id="exampleModalLabel">添加/修改您的搜索内容</h1>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <textarea class="form-control" rows="10" aria-label="搜索内容" id="big-search-input"
                          placeholder="请输入搜索关键词"></textarea>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary" data-bs-dismiss="modal">保存更改
                </button>
            </div>
        </div>
    </div>
</div>


<script src="static/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="static/lib/jquery/dist/jquery.min.js"></script>
<script src="static/lib/sweetalert2/dist/sweetalert2.all.min.js"></script>
<script src="static/lib/dist/js/Jsonp.js"></script>


<script>

    $(document).ready(function () {

        //用于存储jsonp实例
        let jsonp = null;
        //选择的索引
        let selectedIndex = -1;
        //读取缓存中的索引
        let index = localStorage.getItem('index');
        setLogo(index);
        const $searchInput = $('#search-input');
        const $bigSearchInput = $('#big-search-input');
        const $suggestionsWrap = $('.suggestions-wrap');
        const $spBox = $('.sp-box');
        const bigSearchModalEl = document.getElementById('bigSearchModal');
        const bigSearchModalInstance = new bootstrap.Modal(bigSearchModalEl, {
            keyboard: true,
            focus: false
        })

        //监听输入框的input事件
        $searchInput.on('input', function () {
            fetchData()
        })

        $searchInput.on('click', function () {
            if ($suggestionsWrap.is(':empty')) {
                fetchData()
            }
        })

        $(document).on('click', function (event) {
            // 判断是否是排除的元素或其子元素
            if (!$(event.target).is($searchInput)) {
                // 你的代码写在这里
                closeSugWrap() // 清空结果容器
            }
        });

        //该方法只是单纯用来当输入框为空时清空搜索结果
        $searchInput.on('keyup', function () {
            let text = getSearchInputVal()
            if (text === "") {
                closeSugWrap() // 清空结果容器
            }
        })

        //搜索按钮被点击
        $('#search-btn').on('click', function () {
            let text = getSearchInputVal()
            if (text === "") {
                msg('请输入搜索内容')
                return;
            }
            goSearch(text)
        })


        function goSearch(text) {
            if (index === '0') {
                window.location.href = `https://www.baidu.com/s?wd=${text}`
            } else if (index === '1') {
                window.location.href = `https://www.google.com/search?q=${text}`
            } else if (index === '2') {
                window.location.href = `https://www.bing.com/search?q=${text}`
            } else if (index === '3') {
                window.location.href = `https://www.so.com/s?ie=utf-8&q=${text}`
            } else if (index === '4') {
                msg('该搜索引擎暂不支持')
            } else if (index === '5') {
                window.location.href = `https://m.sm.cn/s?q=${text}`
            }
        }

        //搜索框放大
        $('#fullscreen-btn').on('click', function () {
            bigSearchModalInstance.show();
        })


        //删除按钮
        $('#clear-btn').on('click', function () {
            $searchInput.val('')
            closeSugWrap()
        })


        //事件委托,用于切换图标
        $('.search-logo-dropdown-menu').on('click', '.dropdown-item', function () {

            const $item = $(this);
            let dataIndex = $item.attr('data-index')

            //设置logo
            setLogo(dataIndex)

            //存入缓存
            localStorage.setItem('index', dataIndex);

            //更改变量的值
            index = dataIndex;

            //先清空上一次的jsonp请求
            jsonp && jsonp.abort()


            //聚焦(它会自动触发事件)
            setInputFocus($searchInput);

            fetchData();

        })

        //委托用于点击条目
        $suggestionsWrap.on('click', '.list-group-item-action', function () {
            let text = $(this).text();
            $searchInput.val(text);
            goSearch(text)

        })


        function setInputFocus($input) {
            let len = $input.val().length;
            $input[0].focus();
            $input[0].setSelectionRange(len, len);
        }

        function setLogo(index) {
            let logoHtml = '';
            switch (index) {
                case '0':
                    logoHtml = `<img src="static/img/baidu.png" alt="百度搜索" style="width: 16px;">`;
                    break;
                case '1':
                    logoHtml = `<img src="static/img/google.png" alt="谷歌搜索" style="width: 16px;">`;
                    break;
                case '2':
                    logoHtml = `<img src="static/img/bing.png" alt="必应搜索" style="width: 16px;">`;
                    break;
                case '3':
                    logoHtml = `<img src="static/img/360so.png" alt="360搜索" style="width: 16px;">`;
                    break;
                case '4':
                    logoHtml = `<img src="static/img/sougou.png" alt="搜狗搜索" style="width: 16px;">`;
                    break;
                case '5':
                    logoHtml = `<img src="static/img/shenma.png" alt="神马搜索" style="width: 16px;">`;
                    break;
                default:
                    return;
            }
            $('#logo-wrap').html(logoHtml);
        }


        bigSearchModalEl.addEventListener('show.bs.modal', event => {
            $bigSearchInput.val($searchInput.val())
        })

        bigSearchModalEl.addEventListener('shown.bs.modal', event => {
            setInputFocus($bigSearchInput)
        })


        bigSearchModalEl.addEventListener('hide.bs.modal', event => {
            $searchInput.val($bigSearchInput.val());
            setInputFocus($searchInput)
            fetchData()
        })


        // 关闭建议词的下拉列表
        function closeSugWrap() {
            $suggestionsWrap.empty().hide(); // 清空结果容器
        }


        function fetchData() {
            let text = getSearchInputVal();
            if (text) {
                $spBox.html('<span class="spinner"></span>');

                let url = '';
                if (index === '0') {
                    url = `https://suggestion.baidu.com/su?wd=${text}&cb=?`
                } else if (index === '1') {
                    url = `https://suggestqueries.google.com/complete/search?client=youtube&q=${text}&jsonp=?`
                } else if (index === '2') {
                    url = `https://api.bing.com/qsonhs.aspx?type=cb&q=${text}&cb=?`
                } else if (index === '3') {
                    url = `https://sug.so.360.cn/suggest?callback=?&word=${text}`
                } else if (index === '4') {
                    url = `https://sor.html5.qq.com/api/getsug?key=${text}&cb=?`
                } else if (index === '5') {
                    url = `https://sugs.m.sm.cn/web?&q=${text}&callback=?`
                }
                jsonp && jsonp.abort()
                jsonp = new Jsonp(url, 3000);
                jsonp.send()
                    .then((data) => {
                        // 新的组合的数据
                        let newData = [];

                        if (index === '0') {
                            newData = data.s;
                        } else if (index === '1') {
                            //将二维数组中内部元素的字符串类型元素过滤出来，并组成一个一维数组
                            newData = data[1].flatMap(innerArray =>
                                innerArray.filter(element => typeof element === 'string')
                            );

                        } else if (index === '2') {
                            if (data.AS.FullResults === 1) {
                                newData = data.AS.Results.flatMap(result => result.Suggests.map(suggest => suggest.Txt));
                            }
                        } else if (index === '3') {

                            newData = data.result.map(obj => obj.word);

                        } else if (index === '4') {

                            console.log(data)
                        } else if (index === '5') {
                            newData = data.r.map(obj => obj.w)
                        }

                        return newData;

                    })
                    .then((data) => {

                        $spBox.html('');
                        closeSugWrap() // 清空结果容器
                        if (data.length > 0) {
                            let htmlStr = `<ul class="list-group">`;
                            data.forEach(function (suggestText) {
                                htmlStr += `<a class="list-group-item list-group-item-action text-truncate" role="button">${suggestText}</a>`;
                            });
                            htmlStr += `</ul>`;
                            $(htmlStr).appendTo($suggestionsWrap);

                            //再把容器显示
                            $suggestionsWrap.show();
                            //设定索引为-1,重置索引
                            selectedIndex = -1;
                            $searchInput.off('keydown.addHighlight').on('keydown.addHighlight', handleInputKeyDown);
                        }

                    })
                    .catch((error) => {

                        // console.log(error)
                        if (error.message !== 'JSONP request aborted') {

                            $spBox.html('');
                            if (error.message === "JSONP request timed out") {//超时
                                msg('请求超时~,请重试');
                                $searchInput.blur()

                            } else {
                                msg('请求出错~')
                            }
                        }

                    })

            }
        }


        function getSearchInputVal() {
            return $.trim($searchInput.val());
        }


        function handleInputKeyDown(event) {

            const items = document.querySelectorAll('.list-group-item');
            switch (event.code) {
                case 'ArrowUp': {
                    event.preventDefault();
                    if (selectedIndex > 0) {
                        selectedIndex--;
                        const selectedItem = items[selectedIndex];
                        $searchInput.val(selectedItem.textContent)
                    }
                    break;
                }
                case 'ArrowDown': {
                    event.preventDefault();
                    if (selectedIndex < items.length - 1) {
                        selectedIndex++;
                        const selectedItem = items[selectedIndex];
                        $searchInput.val(selectedItem.textContent)
                    }
                    break;
                }
                case 'Enter': {
                    event.preventDefault();
                    if (selectedIndex > -1) {
                        const selectedItem = items[selectedIndex];
                        $searchInput.val(selectedItem.textContent)

                        goSearch(selectedItem.textContent)

                    }
                    break;
                }
                default: {
                    // selectedIndex = -1;
                }
            }


            items.forEach((item, index) => {
                if (index === selectedIndex) {
                    $(item).addClass('active')
                } else {
                    $(item).removeClass('active')
                }
            });
        }


        function msg(title) {
            const Toast = Swal.mixin({
                toast: true,
                position: 'top-end',
                showConfirmButton: false,
                timer: 3000,
                timerProgressBar: true,
                didOpen: (toast) => {
                    toast.addEventListener('mouseenter', Swal.stopTimer)
                    toast.addEventListener('mouseleave', Swal.resumeTimer)
                }
            })

            Toast.fire({
                icon: 'error',
                title: title
            })
        }
    });


</script>
</body>
</html>
